Fork me on GitHub

Using Folium to show geographic data

Introduction

This post demonstrates how to

  • Display a map from OpenStreetMaps using Folium
  • Add custom shape files to define regions of interest
  • Color the regions of interest based on data in a pandas dataframe

The code of this post is available at https://github.com/rsandstroem/IPythonNotebooks/blob/master/GeoMapsFoliumDemo/GeoMapsFoliumDemo.ipynb .

Getting map data and file formats

Using the method described here, you do not need any local map data. The maps are automatically pulled from OpenStreetMap.

However, you might want use concepts such as regions, and you need to define them through files containing those geolocations. There are multiple sources of data which is freely available, in this example we are using shape files from this location: http://data.geo.admin.ch.s3.amazonaws.com/ch.swisstopo.swissboundaries3d-kanton-flaeche.fill/data.zip

We have provided the shape files we will use for this demonstration, normally you would need to retrieve and unpack the map data.

There are many file formats commonly used for maps. In this case what we have are a set of shapefiles. Since we will be working with geojson files in this demonstration you need to convert them to geojson.

A sample geojson file has been supplied with this tutorial, but for reference you can create a geojson file from the shape files from a console like this:

ogr2ogr -f GeoJSON -t_srs EPSG:4326 switzerland.geojson swissBOUNDARIES3D_1_2_TLM_KANTONSGEBIET.shp

You now have a map in your local directory, formatted as a geojson file.

Set up

For this demonstration we need "folium". Install it using

pip install folium

or if you are using the Anaconda you can do

sudo conda install --channel https://conda.binstar.org/IOOS folium

where you can replace the channel with your choice from the options listed by

binstar search -t conda folium

In [1]:
from IPython.display import HTML
import folium

Display the map

First we show the map without any use of the geojson we created from the shapefiles.

In [2]:
kanton_map = folium.Map(location=[46.8, 8.33],
                   tiles='Mapbox Bright', zoom_start=7)
kanton_map
Out[2]:

You should now see an map of Switzerland with surrounding countries and cities. Next, display an OpenStreetMap and overlay the cantons of Switzerland on top.

In [3]:
kanton_map.choropleth(geo_path='switzerland.geojson')
kanton_map
Out[3]:

Import demographics data from a csv into a pandas data frame

Read in some data for the canton's of Switzerland from a csv file. We will display this data on the map we just created.

In [4]:
import pandas as pd
canton_overview = r'Switzerland_overview.csv'
canton_data = pd.read_csv(canton_overview)
canton_data
Out[4]:
Abbr Canton Capital Population Area Density Municipalities Official languages CantonNumber
0 ZH Zurich Zurich 1463459 1729 701 171 German 1
1 BE Bern Bern 1001281 5959 158 383 German, French 2
2 LU Luzern Luzern 390349 1493 233 87 German 3
3 UR Uri Altdorf 35865 1077 33 20 German 4
4 SZ Schwyz Schwyz 151396 908 143 30 German 5
5 OW Obwalden Sarnen 36507 491 66 7 German 6
6 NW Nidwalden Stans 41888 276 138 11 German 7
7 GL Glarus Glarus 39593 685 51 3 German 8
8 ZG Zug Zug 118118 239 416 11 German 9
9 FR Fribourg Fribourg 297622 1671 141 167 French, German 10
10 SO Solothurn Solothurn 261437 790 308 122 German 11
11 BS Basel-Stadt Basel 195962 37 5072 3 German 12
12 BL Basel-Landschaft Liestal 281112 518 502 86 German 13
13 SH Schaffhausen Schaffhausen 78783 298 246 27 German 14
14 AR Appenzell Ausserrhoden Herisau 53691 243 220 20 German 15
15 AI Appenzell Innerrhoden Appenzell 15778 173 87 6 German 16
16 SG St. Gallen St. Gallen 491699 2026 222 85 German 17
17 GR Graubünden Chur 194959 7105 26 180 German, Romansh, Italian 18
18 AG Aargau Aarau 636362 1404 388 220 German 19
19 TG Thurgau Frauenfeld 260278 991 229 80 German 20
20 TI Ticino Bellinzona 346539 2812 110 157 Italian 21
21 VD Vaud Lausanne 749373 3212 188 339 French 22
22 VS Valais Sion 327011 5224 53 143 French, German 23
23 NE Neuchatel Neuchatel 177327 803 206 53 French 24
24 GE Geneva Geneva 479158 282 1442 45 French 25
25 JU Jura Delemont 72410 839 82 64 French 26

Color code the cantons based on their population density

The KANTONSNUM in the json file is used to ensure correct assignment of the data in the demographics data file. Try using the name of the cantons instead. What happens, and why? (Hint: open the geojson file and compare with the csv file.)

In [5]:
kanton_map2 = folium.Map(location=[46.8, 8.33], 
                    zoom_start=7.5)
kanton_map2.choropleth(geo_path='switzerland.geojson', data=canton_data,
             columns=['CantonNumber', 'Density'],
             key_on='feature.properties.KANTONSNUM',
             threshold_scale=[100, 200, 300, 500, 1000, 5000],
             fill_color='BuPu')
kanton_map2
Out[5]:

blogroll

social